home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / basic / bastips2.zip / BASICNTS.TXT < prev    next >
Text File  |  1986-07-02  |  38KB  |  785 lines

  1.                         Maximum Function
  2.      (PC Magazine Vol 5 No 1 January 14, 1986 User-to-User)
  3.  
  4.      BASIC lacks two very fundamental functions -- maximum and minimum.
  5. Instead of using repetitive IF ...THEN ...ELSE statements.  Two user-
  6. defined functions can handle this (MINMAX.BAS).  As an example, if you
  7. wanted to create a formula "Principal payment = Cash flow available -
  8. Interest" but had to be sure the principal payment could not be a
  9. negative and could not be greater than the loan opening balance, create
  10. the following line:  PRIN=FNMIN((FNMAX(CF-INTRST),0),LOAN).
  11.  
  12. 100 'MINMAX.BAS
  13. 110 DEF FNMAX(V1,V2)=INSTR(STR$(V1-V2),"-")*V2+(1-INSTR(STR$(V1-V2),"-"))*V1
  14. 120 DEF FNMIN(V1,V2)=INSTR(STR$(V1-V2),"-")*V1+(1-INSTR(STR$(V1-V2),"-"))*V2
  15. 130 A=10:B=40:X=FNMAX(A,B):PRINT"A=";A,"B=";B,"MAX(A,B)=";X
  16. 140 A=-20:B=10:X=FNMIN(A,B):PRINT"A=";A,"B=";B,"MIN(A,B)'";X
  17.  
  18. -----------------------------------------------------------------
  19.                           Faster Arrays
  20.      (PC Magazine Vol 5 No 1 January 14, 1986 User-to-User)
  21.  
  22.      It can be necessary to load and save large arrays of numbers in
  23. BASIC programs that were stored as sequential files.  Even with the
  24. AT's RAM drive and fast procesing speed, it takes forever to do this.
  25. The trick is to save the array information in binary format.
  26.      First, you have to know the size of the array.  This is determined
  27. by computing the product of each of the array's dimension plus 1.  For
  28. example, if an array is defined by DIM ARRAY(250,20), the actual size
  29. of the array is calculated by SIZE=(250+1)*(20+1)=5271.
  30.      Next, determine the length of memory used to store the array.  The
  31. PC uses 2 bytes to store each element of an integer array, 4 bytes for
  32. each element of a single-precision (!) array, and 8 bytes for each
  33. element of a double-precision (#) array.  Therefore, the amount of
  34. memory used is calculated by computing LENGTH=BYTES*SIZE where BYTES
  35. is 2, 4 or 8, depending on the array type, and SIZE is the figure
  36. computed earlier.
  37.      Finally, know the array's starting address -- where it is located
  38. in memory. This is found by using the VARPTR function, with a statement
  39. ADDRESS=VARPTR(ARRAY(0,0)).  It is very important to set the program
  40. variables before calculating the ADDRESS with VARPTR, since BASIC will
  41. move the location of an array whenever it encounters a new
  42. nondimemsioned variable.
  43.      After running the BSAVER.BAS program, your array will be stored
  44. as a binary file.  To reload the array from the binary file, run the
  45. accompanying BLOADER.BAS program.  This will work on any precision
  46. numbers and arrays with any legal number of dimensions.
  47.      Editor's Note:  This technique does indeed save an enormous amount
  48. of time and disk space.  We ran a 5,000-element integer test on a PC AT
  49. running at 8 MHz.  The FILMAKER.BAS program used a 250 x 20 loop to
  50. create a 5,000-element sequential file (called SEQFILE) consisgint of
  51. the sequential integers from 1 to 5,000.  It took 15 seconds to create
  52. the 38K sequential file.  The BSAVER.BAS program loaded the SEQFILE
  53. sequential file in 13 seconds and wrote it back to disk as a 10K binary
  54. file called YOURFILE.EXT in just 1 second.  The BLOADER.BAS program
  55. reloaded the 5,000-element array from the YOURFILE.EXT file in one
  56. second.  To text this yourself, after running the third program, type
  57. PRINT ARRAY(1,1) and PRINT ARRAY(250,20).  You should see 1 and 5000,
  58. respectively.  This happens so fast that you might want to verify that
  59. the array was not lurking in memory the whole time; you can do this by
  60. entering CLEAR or going in and out of DOS between program steps.
  61.  
  62. 100 'FILMAKER.BAS
  63. 110 DEFINT A-Z:TIME$="0"
  64. 120 OPEN "seqfile" FOR OUTPUT AS #1
  65. 130 FOR A=0 TO 249
  66. 140 FOR B=1 TO 20
  67. 150 PRINT #1,A*20+B
  68. 160 NEXT:NEXT:CLOSE
  69. 170 PRINT "Seq file time ";TIME$
  70.  
  71. 100 'BSAVER.BAS
  72. 110 DEFINT A-Z:TIME$="0"
  73. 120 D1=250:D2=20:ADDRESS=0
  74. 130 FILE$="yourfile.ext"
  75. 140 DIM ARRAY(D1,D2)
  76. 150 OPEN "I",#1,"SEQFILE"
  77. 160 FOR N=1 TO D1
  78. 170 FOR J=1 TO D2
  79. 180 INPUT #1,ARRAY(N,J)
  80. 190 NEXT:NEXT
  81. 200 PRINT "LOADing TIME ";TIME$
  82. 210 TIME$="0"
  83. 220 SIZE=(D1+1)*(D2+1)
  84. 230 LENGTH=2*SIZE
  85. 240 ADDRESS=VARPTR(ARRAY(0,0))
  86. 250 BSAVE FILE$,ADDRESS,LENGTH
  87. 260 PRINT "BSAVEing time ";TIME$
  88.  
  89. 100 'BLOADER.BAS
  90. 110 DEFINT A-Z:TIME$="0"
  91. 120 D1=250:D2=20:ADDRESS=0
  92. 130 FILE$="yourfile.ext"
  93. 140 DIM ARRAY(D1,D2)
  94. 150 ADDRESS=VARPTR(ARRAY(0,0))
  95. 160 BLOAD FILE$,ADDRESS
  96. 170 PRINT "BLOADer time ";TIME$
  97.  
  98.  
  99. -----------------------------------------------------------------
  100.                         BASIC Vocabulary
  101.                 (COMPUTE! Magazine date unknown)
  102.  
  103.      You can write a "vocabulary" in BASIC so the computer understands
  104. dozens of words without using IF statements to check for every word.
  105. Create the vocabulary with arrays.  Unlike a simple variable which
  106. equates to a single numeric value (A=1) or string of characters
  107. (A$="HELLO"), an array is a group of related data items.  This short
  108. example creates a rudimentary vocabulary with string arrays.
  109.  
  110.  
  111. 100 DIM VB$(4),OB$(4):FOR J=1 TO 4:READ A$,B$
  112. 110 VB$(J)=A$:OB$(J)=B$:NEXT J
  113. 120 DATE TAKE,GOLD,PUT,SWORD,EAT,FOOD,THROW,ROCK
  114. 130 SP=0:I$="":VB$="";OB$="":PRINT "YOUR COMMAND: ";
  115. 140 INPUT I$:FOR J=1 TO LEN(I$):T$=MID$(I$,J,1)
  116. 150 IF T$=CHR$(32) THEN SP=1:GOTO 180
  117. 160 IF SP=1 THEN OB$=OB$+T$
  118. 170 IF SP=0 THEN VB$=VB$+T$
  119. 180 NEXT J:VB=0:FOR J=1 TO 4
  120. 190 IF VB$=VB$(J) THEN VB=J
  121. 200 NEXT J
  122. 210 IF VB=0 THEN PRINT "DON'T UNDERSTAND ";VB$:GOTO 130
  123. 220 OB=0:FOR J=1 TO 4:IF OB$=OB$(J) THEN OB=J
  124. 230 NEXT J
  125. 240 IF OB=0 THEN PRINT "DON'T UNDERSTAND ";OB$:GOTO 130
  126. 250 PRINT "VERB #";VB;", OBJECT #";OB:GOTO 130
  127.  
  128.      Lines 100-120 store the vocabulary in two string arrays.  The
  129. array named VB$() holds four verb strings (TAKE,PUT,EAT and THROW)
  130. and the OB$() array holds four object strings (GOLD, SWORD, FOOD and
  131. ROCK).
  132.      Once the arrays are set up, each word can be referenced by the
  133. index number that identifies its position within the array.  For
  134. instance, in response to the statement PRINT V$(1), the computer
  135. prints TAKE.  The statement IF A$=OB$(1) is true when A$ equals GOLD,
  136. and so on.  Since the vocabulary has been reduced to reference numbers,
  137. you can cycle through the arrays with simple FOR-NEXT loops, testing
  138. whether your input words match anything in the vocabulary.  This is
  139. far more efficient than using a multitude of IF statements.
  140.      Lines 140-180 bring the input sentence into the computer as one
  141. string (I$) and break it into two parts: the verb string V$ and the
  142. object string O$.  Note that simple (nonarray) variables like V$ and
  143. O$ are distinct from array variables like V$() and O$().  The program
  144. uses a primitive method to extract verb and object from the input
  145. sentence.  It looks for the space character that separates the words,
  146. assigning every character before the space to V$, and everything after
  147. it to O$.
  148.      Once the verb and object have been extracted, lines 180-200
  149. compare the verb string V$ to every verb in the vocabulary array V$().
  150. The variable V signifies the verb number.  As soon as V$ matches up
  151. with a word in V$(), V records the V$() index number for future
  152. reference.  If V$ isn't found in the vocabulary, line 210 prints the
  153. unknown word and permits another attempt.  A similar loop in lines
  154. 220-230 compares the object string O$ to each word in the O$() array,
  155. and records the object number in the variable O.
  156.      Using arrays makes your program far easier to modify.  For
  157. instance, if you've written an adventure using dozens (or hundreds) of
  158. separate IF statements, and then decide to change one of the vocabulary
  159. words.  It could take hours to locate and change every line that uses
  160. that word.  If your vocabulary is stored in arrays, you can make the
  161. same change in seconds, by replacing the word in a DATA statement.  To
  162. expand the vocabulary, just add more DATA items and increase the values
  163. in the DIM statement and FOR-NEXT loops accordingly.
  164.      Of course, there's much more to writing a playable adventure.
  165. But arrays can help there, too.  Use a room description array to store
  166. the description strings for each room, and a room connection array to
  167. show the connections between them.  The location of each object can be
  168. stored in an object location array, and so on.  You'll want a more
  169. sophisticated parsing routine, however, to pick apart the input
  170. sentence.
  171.  
  172. -----------------------------------------------------------------
  173.                        New BASIC Functions
  174.               (PC World October 1985 Star-Dot-Star)
  175.  
  176.      The MIN function, which returns the lesser of two values supplied,
  177. and the MAX function, which returns the greater, are not available in
  178. BASIC(A).  For example, if you set variable A to 3 and variable B to 7,
  179. executing the statement X=MIN(A,B) sets the value of X to 3.  The
  180. statement X=MAX(A,B) would set X to 7.
  181.      The two lines of BASIC shown below are BASIC statements to create
  182. user-defined functions for MIN and MAX.  Due to the design of the PC's
  183. BASIC, the letters FN must precede the name of each function. Also, the
  184. lines must be executed before the functions are used, so it's a good
  185. idea to put them near the top of your program.
  186.  
  187. 10 DEF FNMIN(A,B)=-B*(B<A)-A*(A<B)
  188. 20 DEF FNMAX(A,B)=-B*(B>A)-A*(A>B)
  189.  
  190.                       MIN and MAX Revisions
  191.               (PC World January 1986 Star-Dot-Star)
  192.  
  193.      Both functions in "New BASIC Functions" (above) return 0 if inputs
  194. are equal.  Here are corrected versions:
  195.  
  196. 10 DEF FNMIN(A,B)=A+(A-B)*(A<B)
  197. 20 DEF FNMAX(A,B)=A+(A-B)*(A>B)
  198.  
  199. FNMIN(A,B) returns the smaller value of A and B, and FNMAX(A,B) returns
  200. the larger value.
  201.  
  202.  
  203. -----------------------------------------------------------------
  204.                         BASIC Conversions
  205.          (PC Magazine Vol 5 No 3 Feb 11, 1986 PC Tutor)
  206.  
  207.      When you save a BASIC program, it is normally stored on disk in a
  208. tokenized format -- that is, all the keywords are replaced with 1-byte
  209. numbers to save space.  You can save a BASIC program in ASCII format
  210. by following the filename in the SAVE command with a comma and an A.
  211. The ASCII files take up more space on disk, but you can use TYPE and
  212. PRINT on them.
  213.      You can use redirection of standard output to make a file that
  214. the BASIC interpreter can read with redirection of standard input to
  215. convert all BASIC files to ASCII format.  First, you create a small
  216. file called LOADSAVE.BAT:
  217.  
  218. echo load "%1" >> convert
  219. echo save "%1",A >> convert
  220.  
  221. The double angle bracket means append the text following the ECHO
  222. command to the file CONVERT.  The "text" written into CONVERT will
  223. consist of just BASIC commands.  Next, create a two-line batch file
  224. called MAKEFILE.BAT:
  225.  
  226. del convert
  227. for %%x in (*.bas) do command /c loadsave %%x
  228.  
  229. The DEL command gets rid of any existing CONVERT file so you start
  230. from scratch.  When you run MAKEFILE.BAT on the DOS command level, the
  231. FOR command will execute LOADSAVE.BAT for every BASIC file on your
  232. disk (or hard disk subdirectory), passing to it a parameter with the
  233. name of the batch file.  LOADSAVE.BAT will create a file called CONVERT
  234. that contains BASIC commands to load each file and save it with the
  235. ASCII option.
  236.      After you run MAKEFILE.BAT to create CONVERT, all you have to do
  237. is execute the command:  BASICA < CONVERT.  BASICA will load all your
  238. BASIC files and save them in ASCII format.  Then you can use the PRINT
  239. command.
  240.      If you don't want to convert them to ASCII format but just want
  241. to print them all out, you can do something similar by creating the
  242. following two files.  First, LOADLIST.BAT:
  243.  
  244. echo load "%1" >> listall
  245. echo llist >> listall
  246. echo lprint chr$(12); >> listall
  247.  
  248. Second, MAKEFILE.BAT:
  249.  
  250. del listall
  251. for %%x in (*.bas) do command /c loadlist %%x
  252.  
  253. Run MAKEFILE.BAT to create LISTALL and then execute:  BASICA < LISTALL.
  254. Notice that a printer form feed using CHR$(12) is included so each
  255. BASIC file listing will start on a new page when printing a disk full
  256. of BASIC files.
  257.  
  258. -----------------------------------------------------------------
  259.                        Recurring Intruder
  260.             (PC World February 1986 The Help Screen)
  261.  
  262.      Attempts to use the Epson FX-100 printers' "bit image mode" have
  263. failed.  A small, twisted line appears at regular intervals within an
  264. image.  These tiny squiggles are the result of the carriage return and
  265. line feed codes (ASCII 13 and 10) that BASIC sends to the printer after
  266. every 80 characters.  (In bit image mode, a "character" is a vertical
  267. pattern one dot wide and up to eight dots high.)  Although these
  268. printer control codes are necessary to print text properly in text
  269. mode, they are interpreted as graphics data when the printer is in
  270. bit image mode.
  271.      Editor's solution:  You may already be using the BASIC statements
  272. WIDTH "LPT1:",80 and WIDTH "LPT1:",132, thereby switching the printer's
  273. line width to accomodate 80- and 132-column paper.  You can use any
  274. from 0 to 254 to specify the number of characters on a line; BASIC will
  275. insert a carriage return/line feed sequence after the requisite number
  276. of characters has been sent to the printer.  But using a value of 255
  277. disables line folding (inserting the CR/LF sequence).  Before you send
  278. bit image mode data to the printer, add the statement WIDTH "LPT1:",255
  279. and remember to reset the printer's line width before printer in text
  280. mode.
  281.  
  282. -----------------------------------------------------------------
  283.                           Dummy Numbers
  284.        (PC Magazine Vol 5 No 6 Mar 25, 1986 User-to-User)
  285.  
  286.      One way to trace the flow of BASIC programs that contain lots of
  287. GOTO statements is to use a technique called backtracking.  If lines
  288. 300, 500, and 700 all contain a GOTO 900, simply insert a line 899
  289. that says:  899 ZZ=9:ON ZZ GOTO 300,500,700.  ZZ can be a numbered
  290. junction point in a program flow chard, or it can be a dummy number.
  291. However, it must be larger than the number of program lines after the
  292. GOTO.  (In this example, there were three line numbers after GOTO, so
  293. ZZ could have just as easily been equal to 4.)  This trick lets you
  294. figure out which possible lines sent the program execution to that
  295. point.
  296.      Editor's Note:  This is a variation of an old trick to start off
  297. programs with a cascade of unused GOTOs with descriptive REM statements
  298. following them.  For instance, you could identify the set up, main
  299. loop, etc. by beginning code with the lines:
  300.  
  301. 100 GOTO 170
  302. 110 GOTO 160  'SETUP
  303. 120 GOTO 300  'MAIN LOOP
  304. 130 GOTO 350  'INPUT ROUTINE
  305. 140 GOTO 400  'ERROR TRAPS
  306. 150 GOTO 500  'PRINTER
  307. 160 'SETUP STARTS NEXT LINE
  308. 170 DEFINT A-Z:CLS
  309.  
  310. The initial GOTO 170 in line 100 jumps the program execution around all
  311. the lines from 110 through 160, which contain remarks that label the
  312. various parts of the program and which will continue to refer to the
  313. proper lines even after renumbering.
  314.      Renumbering can often cause devastating results if done too
  315. casually.  One of the most dreaded messages is an "Undefined line 620
  316. in 850" right after you've just removed 20 lines of code; after
  317. renumbering, these two line numbers could be anywhere.  And if you
  318. don't catch the missing line, your program is destined for doom.  The
  319. obvious solution is to save early and often, especially right before
  320. you start meddling with the code.  Then if the renumbering process
  321. uncovers undefined lines, you can load the previous version and start
  322. again.
  323.      A crafty solution that's been around is to type in two very high
  324. dummy RENUM numbers before you try the real thing.  If you code is
  325. short, typing in RENUM 9999,9999 will uncover undefined lines before
  326. actually changing anything.  This gives you a chance to correct the
  327. mistake before it's too late.  If your program is larger, you might
  328. have to use RENUM 65000,65000.  One advantage of the shorter technique
  329. is that you can put the whole RENUM 9999,9999 on a single function key
  330. -- to do this to F10, add a line at the beginning or the program:
  331.  
  332. 10 KEY 10,"RENUM 9999,9999"
  333.  
  334. Since BASIC will assign a maximum of 15 keystrokes to each function
  335. key and the new definition is exactly 15 characters long, you'll have
  336. to hit Enter after hitting F10.
  337.  
  338. -----------------------------------------------------------------
  339.                          Popping to DOS
  340.                (PC World March 1986 Star-Dot-Star)
  341.  
  342.      POP2DOS.BAS lets users interrupt BASIC programs at any time to
  343. execute DOS commands.  This technique works with BASICA v2.0 and v2.0
  344. of the IBM BASIC Compiler.  When you press F1 the routine saves and
  345. clears the screen and then loads DOS.  You can execute any DOS command
  346. and even run other programs such as DISKCOPY and FORMAT.  When you're
  347. done, type EXIT and press Enter to return to the program, restoring
  348. the screen and putting you back where you began.
  349.      Because there is no easy way for the routine to determine the
  350. current screen mode, your program must set the variable SCRNFLAG% to
  351. note the current mode.  Setting SCRNFLAG% to 0 indicates an 80-column
  352. text mode; set SCRNFLAG% to 1 just before working with medium-
  353. resolution graphics, and set it to 2 before any high-resolution
  354. graphics.  Be sure to reset SCRNFLAG% to 0 when you reset the screen
  355. to text mode.
  356.      When exiting to DOS, be sure that your programs have not left
  357. open any partially written files, lest the user decide to engage in
  358. disk operations that adversely affect the open files (for example,
  359. changing disks or deleting files).
  360.  
  361. 100 DIM GRAPHARRAY%(8004)
  362. 110 SCRNFLAG%=0:ON KEY(1) GOSUB 25000:KEY(1) ON
  363.   .
  364.   .
  365. 25000 IF SCRNFLAG%<>1 THEN 25050
  366. 25010 GET (0,0)-(319,199),GRAPHARRAY%
  367. 25020 SCREEN 0,1,0,0:WIDTH 80:CLS:SHELL
  368. 25030 CLS:SCREEN 1,0:PUT (0,0),GRAPHARRAY%,PSET
  369. 25050 RETURN
  370. 25050 IF SCRNFLAG%<>2 THEN 25100
  371. 25060 GET (0,0)-(639,199),GRAPHARRAY%
  372. 25070 SCREEN 0,1,0,0:CLS:SHELL
  373. 25080 CLS:SCREEN 1,0:PUT (0,0),GRAPHARRAY%,PSET
  374. 25090 RETURN
  375. 25100 SCRNY%=CSRLIN:SCRNX%=POS(0)
  376. 25110 SCREEN 0,1,1,1:CLS:SHELL
  377. 25120 CLS:SCREEN 0,1,0,0:LOCATE SCRNY%,SCRNX%
  378. 25130 RETURN
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.                           Window Wonder
  387.                (PC World March 1986 Star-Dot-Star)
  388.  
  389.      UPDOWN.BAS shows how easily BASICA v2.0 can be made to print
  390. upside down.  Line 140 of the program uses the GET statement to
  391. capture a part of the screen, line 150 uses the WINDOW statement to
  392. reverse the direction of the screen's y coordinate, and line 160
  393. PUTs the captured image back onto the screen.  Because the y coordinate
  394. has been transposed, the resulting image appears upside down.
  395.  
  396. 100 'Upside down graphics
  397. 110 DIM IMAGE(100)
  398. 120 SCREEN 1,0:CLS:KEY OFF
  399. 130 LOCATE 12,15:PRINT "BASIC EXPERT"
  400. 140 GET (112,80)-(207,95),IMAGE
  401. 150 WINDOW (0,0)-(319,199(
  402. 160 PUT (112,96),IMAGE
  403. 170 A$=INPUT$(1)
  404. 180 END
  405.  
  406.  
  407. -----------------------------------------------------------------
  408.                           BASIC Values
  409.               (PC World April 1986 The Help Screen)
  410.  
  411.      Rounding errors occur in IBM BASIC.  For example, if you type
  412. PRINT 9.4, BASIC prints 9.399999.  It performs similar transformations
  413. on hundreds of numbers (8.4, 8.86, 9.02, 9.1 and 9.31 to list a few).
  414. This is because BASIC stores numbers as binaries (base 2).  When a
  415. numeric variable is assigned a number as in A = 10, BASIC converts the
  416. ASCII character string 10 into a binary value, then stores that value
  417. in memory as a string of on and off bits representing 1s and 0s.  When
  418. the value of a numeric variable is printed, BASIC converts the stored
  419. binary value into a string of decimal digits.  For whole numbers, this
  420. presents no problem; every whole decimal number can be converted to a
  421. unique binary number consisting of a finite number of binary digits,
  422. and vice versa.  For fractions, however, this translation creates
  423. problems.  Take, for example, the value .1 in base 3.  This value
  424. cannot be represented with a finite number of base 10 digits and is
  425. thus written as an approximation:  .33 or .33333 or .33333333, etc.,
  426. depending on the number of digits allowed.  This idiosyncrasy persists
  427. with double-precision numbers, but because they are stored with a
  428. greater number of binary digits, conversion errors are less critical,
  429. particularly in money matters.  Even double-precision numbers can ruin
  430. a programmer's day:  Imagine your check-balancing program warning that
  431. your checkbook is out of whack when the program finds that the last
  432. balance plus the total value of deposits (say $9.40) doesn't equal the
  433. remaining balance plus the total value of withdrawals (say $9.399999).
  434.      Programs that demand decimal accuracy rely on another method of
  435. numeric storage.  That technique is called binary coded decimal (BCD);
  436. with it, every digit of a decimal number (or, in an alternate form of
  437. BCD, every two digits) is stored in a single byte.  The BCD approach
  438. avoids both errors and approximations, but like double-precision
  439. numbers in BASIC, calculations are slow and storage requirements
  440. increase.
  441.      You can use single-precision values for monetary dealings if
  442. you're willing to keep sums below $100,000.00 (or $10,000,000 is you
  443. can manage to skip the pennies).  Just work in whole values and use
  444. PRINT USING "$$####.##";x/100 (or use PRINT USING "$$######";x) when
  445. you need to print.
  446.  
  447. -----------------------------------------------------------------
  448.                     Matching BASIC Functions
  449.               (PC World April 1986 The Help Screen)
  450.  
  451.      The following code executes flawlessly:
  452.  
  453. 10 INPUT A$
  454. 20 A$ = CHR$(ASC(A$)-32)
  455. 30 PRINT A$
  456.  
  457. The respective uppercase character is printed when a lowercase
  458. character is entered.  If the identical coding for line 20 is entered
  459. into a define function (DEF FN), as in:
  460.  
  461. 10 DEF FNupper(LOW$) = CHR$(ASC(LOW$)-32)
  462. 20 INPUT A$
  463. 30 A$ = FNupper(A$)
  464. 40 PRINT A$
  465.  
  466. a "Type mismatch in 30" error message occurs.
  467.      The problem is that the string variable A$ and the (incorrect)
  468. numeric variable FNupper are the mismatched types in the code.  Change
  469. line 10 to:  DEF FNupper $(LOW$) = CHR$(ASC(LOW$)-32)  and line 30 to:
  470. A$ = FNupper$(A$).  These differ from the original lines only in that
  471. the dollar signs are inserted directly after the name of the string
  472. function and before the opening parenthesis.
  473.  
  474. -----------------------------------------------------------------
  475.                        Leaving Work Early
  476.          (PC Magazine Vol 5 No 7 Apr 15, 1986 PC Tutor)
  477.  
  478.      It is possible to run a batch job at a set time each day.  One
  479. way to do this is by using the statement:  BASICA GOHOME.BAS  as the
  480. first line in a batch file.  The GOHOME.BAS program below simply loops
  481. until 17:30 (5:30 p.m.), at which point it exits to the system so the
  482. batch file can continue.
  483.      Line 20 is not strictly needed.  However, it serves the function
  484. of giving coworkers the impression that your PC is doing some important
  485. work and that you've stepped away from your desk for a moment.  They
  486. will be less inclined to turn off your machine.
  487.  
  488. 10 WHILE TIME$ < "17:30:00"
  489. 20   PRINT RND,
  490. 30 WEND
  491. 40 SYSTEM
  492.  
  493.  
  494.  
  495.  
  496.                            Free Stamps
  497.        (PC Magazine Vol 5 No 8 Apr 29, 1986 User-to-User)
  498.  
  499.      STAMP.BAS automatically updates the date and time in its own REM
  500. statements each time you run it and then writes the new information to
  501. disk.  The program first looks for the beginning of the program in
  502. memory by peeking at addresses &h30 and &h31, then searching memory
  503. for the { } brackets.  Once it's found them, it pokes the appropriate
  504. bytes of date and time into memory and saves the changed program.
  505.      The subroutine in lines 140 through 190 can be put into any
  506. program to add the current date and time automatically.  If you do
  507. this, be sure to insert an initial {dddddddddd} and {tttttttt} near
  508. the beginning of the program.  Afterward, each time you run the
  509. program the subroutine will log your use.  The DOS directory listing
  510. will log the creation or change of a file, but not its normal running.
  511.  
  512. 100 'STAMP.BAS: Auto Date-Time stamper
  513. 110 'Last Run Date {dddddddddd}
  514. 120 'Last Run Time {tttttttt}
  515. 130 GOSUB 140:END
  516. 140 DEF SEG:C=PEEK(&H30)+256*PEEK(&H31):L=10:A$=DATE$
  517. 150 IF PEEK(C)=123 AND PEEK(C+L+1)=125 THEN 160 ELSE C=C1+1:GOTO 150
  518. 160 FOR I=1 TO L:POKE I+C,ASC(MID$(A$,I,1)):NEXT:C=C+12
  519. 170 IF L=10 THEN L=8:A$=TIME$:GOTO 150
  520. 180 SAVE "STAMP
  521. 190 RETURN
  522.  
  523.  
  524. -----------------------------------------------------------------
  525.                        Scan Code Shortcut
  526.        (PC Magazine Vol 5 No 10 May 27, 1986 User-to-User)
  527.  
  528.      Most programmers trap extended key combinations such as PgUp,
  529. Shift-F1, Ins or Ctrl-PrtSc with routines like:
  530.  
  531. 100 I$=INKEY$
  532. 110 IF I$="" THEN 100
  533. 120 IF LEN(I$)<2 THEN 100
  534. 130 IF ASC(MID$(I$,2))=82 THEN ....
  535.  
  536. A simple solution relies on the MKI$ function to convert an integer
  537. into a 2-byte string.  Recode lines 120 and 130 as:
  538.  
  539. 120 IF I$=MKI$(&H5200) THEN ....
  540.  
  541. to simplify the expression and pick out what is going on much faster.
  542.      When INKEY$ returns a two-character ("extended") code, the first
  543. is always a null, or CHR$(0).  In the &H5200 example above, the 00 at
  544. the end represents CHR$(0), while the &H52 is the hex representation
  545. of 82 (the Ins key).
  546.      To use this technique, look up the decimal value of the key or key
  547. combination in the BASIC manual chart, convert it to hex, precede it
  548. with a "&H", and follow it with a pair of zeros.  This results in BASIC
  549. code that is easier to read, easier for the machine to execute, and a
  550. lot less typing.
  551.      Editor's Note:  If you're testing many keys with extended codes,
  552. you can do a single check for the initial null and use a long INSTR
  553. string to identify all the keys quickly.  SCANNER.BAS is an example:
  554.  
  555. 100 'SCANNER.BAS
  556. 110 PRINT "Hit cursor pad keys ...";
  557. 120 PRINT "Or hit Esc to quit."
  558. 130 FOR A=1 TO 10:READ A$:B$(A)=A$:NEXT
  559. 140 I$=INKEY$:IF I$="" THEN 140
  560. 150 IF I$=CHR$(27) THEN END
  561. 160 IF LEN(I$)<2 THEN BEEP:GOTO 140
  562. 170 S=INSTR("GHIKRMOPQS",RIGHT$(I$,1))
  563. 180 PRINT B$(S);" key":GOTO 140
  564. 190 DATA Home,CsrUp,PgUp,CsrLeft,Ins
  565. 200 DATA CsrRight,End,CsrDown,PgDn,Del
  566.  
  567. -----------------------------------------------------------------
  568.                      .EXE to .COM Conversion
  569.          (PC Magazine Vol 5 No 10 May 27, 1986 PC Tutor)
  570.  
  571.      Compiled BASIC programs in .EXE format cannot be converted to
  572. a .COM format.  This is not really a problem, however, since the .EXE
  573. format files are directly executable by DOS without conversion.
  574.      Only .EXE files that have been specially prepared (generally in
  575. assembly language) can successfully be turned into .COM files.  These
  576. progarms must not contain a stack segment, they must have no references
  577. to relocatable segments, and they must begin execution at offset 100h
  578. in the file.  Since an executable .EXE file must have a stack segment
  579. and generally uses separate code and data segments, the two formats
  580. are essentially incompatible.
  581.      The .COM format has a few advantages over the .EXE format, notably
  582. a smaller size and slightly easier assembly language programming for
  583. small programs.  However, .COM files are limited to about 65,000 bytes.
  584. (The .COM fornat was adapted from the CP/M operating system, which had
  585. only a 64K address space.)
  586.      Don't be too eager to convert your programs to .COM files.  The
  587. COM format is an endangered species.  The mix of code and data in the
  588. same segment and the calculation of the segment address outside the
  589. code segment are two of the major blocks that limit PC programs to one
  590. megabyte of addressable memory and prevent them from running under the
  591. PC AT 80286 protected mode.  If a future version of PC-DOS supports
  592. the 80286 protected mode, it will probably not support the .COM file
  593. format at the same time.
  594.  
  595.  
  596. -----------------------------------------------------------------
  597.                         Different BASICs
  598.          (PC Magazine Vol 5 No 10 May 27, 1986 PC Tutor)
  599.  
  600.      The PC-DOS BASIC interpreter for the IBM PC and the MS-DOS BASIC
  601. interpreter for IBM-compatibles both come from Microsoft and function
  602. similarly.  But structurally they are quite different.  In general,
  603. techniques that access specific memory locations within the interpreter
  604. (as does the "unprotect" scheme) can not be used on both versions of
  605. BASIC.
  606.      The IBM PC has an entire self-contained (but limited) BASIC
  607. interpreter coded in a ROM inside the PC.  For the very early PCs,
  608. IBM included this under the assumption that lots of people might be
  609. using the PC without disk drives and storing BASIC programs to cassette
  610. tape.  With marketing assumptions like this, no wonder IBM was
  611. surprised at how the PC took off!  Even on the PC AT, however, ROM
  612. BASIC is still included with the machine.  The PC-DOS versions of
  613. BASIC and BASICA uses routines in the ROM BASIC module.  In fact, the
  614. PC-DOS BASIC and BASICA interpreters are sometimes referred to as
  615. "extensions" of ROM BASIC.  This makes the BASIC.COM and BASICA.COM
  616. files shorter, but it limits their use to the IBM PC.  IBM-compatible
  617. machines cannot include the IBM ROM version of BASIC because it is
  618. proprietary.
  619.      Versions of MS-DOS for compatibles generally come with a version
  620. of BASIC called GWBASIC but may also include files named BASIC and
  621. BASICA, which are identical copies of the GWBASIC interpreter.  (On
  622. the PC, BASIC and BASICA are different.)  The "GW" of GWBASIC is either
  623. the reversed initials of Microsoft Chairman William Gates (better known
  624. as Bill Gates), or it stands for "Gee Whiz."
  625.      Since PC-DOS runs on many compatibles, many IBM-compatible users
  626. have switched to PC-DOS.  The only real problem is that the PC-DOS
  627. BASIC interpreters won't work, so they have to use the GWBASIC included
  628. with their compatibles' MS-DOS.
  629.      Microsoft does not sell DOS to the general public (instead it
  630. licenses it to companies making MS-DOS computers), but PC-DOS is
  631. available at any IBM Product Center and other computer stores.  For
  632. the PC-compatible owners running PC-DOS, Microsoft sells separately
  633. a version of GWBASIC that does not need the PC ROM BASIC.
  634.  
  635. -----------------------------------------------------------------
  636.                        IBM BASIC Directory
  637.                   (COMPUTE! Magazine June 1986)
  638.  
  639.      There are two ways to read and display the disk directory on an
  640. IBM PC from with a BASIC program.  The first is simply to print the
  641. directory to the screen at the appropriate time in your BASIC program.
  642. This routine asks you from which drive A: or B:) you want to read the
  643. directory.  If you have a single-drive system (drive A: only), remove
  644. the REM from line 100.
  645.  
  646. 100 REM FSPEC$="A:*.*":GOTO 140
  647. 110 PRINT:PRINT "Select drive: (";:COLOR 16,15:PRINT"A B";:COLOR 7,0:
  648.     PRINT CHR$(29)CHR$(29)"/"CHR$(28)")"
  649. 120 DRIVE$=INKEY$+":":A=ASC(DRIVE$):IF (A OR 32)<97 OR (A OR 32)>98
  650.     THEN 120
  651. 130 DRIVE$=CHR$(A AND 223)+":":FSPEC$=DRIVE$+"*.*"
  652. 140 ON ERROR GOTO 150:FILES FSPEC$:ON ERROR GOTO 0:END
  653. 150 BEEP:COLOR 31:CLS:PRINT "Cannot read directory":COLOR 7:ON ERROR
  654.     GOTO 0:END
  655.  
  656.      The second method reads the directory into a string array for use
  657. by your program at some later point.  This routine reads the filenames
  658. from the disk directory into an array named F$.  One advantage of this
  659. method is that you need to look only once at the directory.  Once the
  660. directory information is stored in a string, you can extract the file-
  661. names whenever it's convenient and print them in any format you like.
  662. With a little more programming, you could cursor through the directory
  663. to access a particular file, sort the directory entries alphabetically,
  664. catalog all your disks, or whatever.  Remove the REM from line 1000 if
  665. you have a single-drive system.
  666.  
  667.  
  668. 1000 REM FSPEC$="A:*.*":GOTO 1040
  669. 1010 PRINT:PRINT "Select drive: (";:COLOR 16,15:PRINT"A B";:COLOR 7,0:PRINT CHR$929)CHR$(29)"/"CHR$(28)")"
  670. 1020 DRIVE$=INKEY$+":":A=ASC(DRIVE$):IF (A OR 32)<97 OR (A OR 32)>98 THEN 1020
  671. 1030 DRIVE$=CHR$(A AND 223)+":":FSPEC$=DRIVE$+"*.*"
  672. 1040 DEF SEG=0:WIDTH 80
  673. 1050 HEAD=1050:TAIL=1052:BUFFER=1054
  674. 1060 CLS:COLOR 23,0,0:PRINT"Reading disk directory"
  675. 1070 COLOR 0:ON ERROR GOTO 1090
  676. 1080 FILES FSPEC$:ON ERROR GOTO 1100
  677. 1090 BEEP:COLOR 31:CLS:PRINT "Cannot read directory":COLOR 7:ON ERROR GOTO 0:END
  678. 1100 DIM TT$(24):LOCATE 3,1:COLOR 7:ROWS=0
  679. 1110 POKE HEAD,30:POKE TAIL,34:POKE BUFFER,0:POKE BUFFER+1,79:POKE BUFFER+2,13:POKE BUFFER+3,28:'Put code for End, Enter into keyboard
  680. 1120 LINE INPUT TT$(ROWS):IF TT$(ROWS)<>"" THEN ROWS=ROWS+1:GOTO 1110
  681. 1130 IF NOT DIMMED THEN DIM F$(ROWS*4-1):DIMMED=1
  682. 1140 ROWS=ROWS-1:FOR I=0 TO ROWS:FOR J=0 TO 3
  683. 1150 T$=MID$(TT$(I),J*18+1,12)
  684. 1160 IF T$<>"" THEN F$(ENTRIES)=T$:ENTRIES=ENTRIES+1
  685. 1170 NEXT J:NEXT I:ERASE TT$:ENTRIES=ENTRIES-1:DEF SEG:RETURN
  686.  
  687.  
  688. -----------------------------------------------------------------
  689.                       Screen Pages in BASIC
  690.         (PC Magazine Vol 5 No 11 June 10, 1986 PC Tutor)
  691.  
  692.      When using the color/graphics adapter in 80-column text mode, you
  693. can store four video pages.  (In 40-column text mode, you can store
  694. eight pages.)  Only one page is visible at a time, but you can write
  695. to the other three (or seven) pages and then quickly flip to them
  696. later.  The SCREEN command is used to select both which video page you
  697. want to write to and which page you want to have displayed.
  698.      SCREEN takes four parameters.  In text mode, the first parameter
  699. is a 0.  The second parameter is a 1 to enable color.  (You'll probably
  700. use 0 to disable color only if you use a black-and-white display driven
  701. through the composite output jack on the display adapter.)  The third
  702. parameter selects which of the four (or eight) pages subsequent screen
  703. output statements will write to.  The fourth parameter determines which
  704. of these four (or eight) pages is displayed.  The pages are numbered 0,
  705. 1, 2, and 3 (or up to 7 with a 40-column display).
  706.      The short BASIC program below demonstrates this.  Lines 10 and 20
  707. write one line on each of the four pages while continuing to display
  708. page 0.  Line 40 writes another line on page 0.  By pressing the 0, 1,
  709. 2, or 3 keys, you can see the other three pages.
  710.      Note that BASIC does not maintain a different cursor for each of
  711. the pages.  Each of the text lines in this demonstration program is
  712. spaced a line lower, just as if they were all written to the same page.
  713. You have to handle the cursor problem yourself when using video pages.
  714. You can get the current cursor position with the POS and CSRLIN
  715. functions and set it with LOCATE.
  716.      Graphics present a whole different story.  The color/graphics
  717. adapter has only enough memory for one video page when using either
  718. the 320-dot by 200-line four-color graphics mode or the 640-dot by
  719. 200-line two-color graphics mode.  BASIC has various built-in commands
  720. to work with graphics and to perform some crude animation, so you might
  721. consider programming a simulated operation of your products rather than
  722. flip different images to the screen.  The BASIC command BSAVE and BLOAD
  723. can, respectively, save a graphics screen image to a disk file and
  724. retrieve it, but the speed of these commands, even in a compiled BASIC
  725. program, will probably be unsatisfactory.  (IBM's Enhanced Graphics
  726. Adapter can store multiple graphics pages, but BASIC does not yet
  727. support it.)
  728.      One compromise that may prove easier to use may be "Character
  729. Graphics."  In character mode, you have access to a variety of lines,
  730. blocks, and other graphics symbols that can often be successfully
  731. combined to make effective and easily manipulated 16-color drawings.
  732. The available graphics symbols are shown in Appendix G of the BASIC
  733. 2.0 manual and Appendix D of the BASIC 3.0 manual.  For an example of
  734. the variety of images that you can make using these characters, take
  735. a look at IBM's monochrome display version of the "Introduction to the
  736. IBM PC" disk.
  737.  
  738. -----------------------------------------------------------------
  739.                    Run BASIC Programs From DOS
  740.               (PC World The Help Screen June 1986)
  741.  
  742.      This procedure simplifies the procedure for running a BASIC
  743. program without having to learn how to load the BASIC interpreter
  744. and then loading and running a particular BASIC program.  Create
  745. RUN.BAT (below), place the program disk in drive B:, insert the disk
  746. containing BASIC and RUN.BAT in drive A:, and type A:RUN progname,
  747. where progname is the name of the desired BASIC program in drive B:.
  748. If RUN is entered without a program name, RUN.BAT will display a list
  749. of the BASIC programs in drive B:.
  750.  
  751. echo off
  752. cls
  753. a:
  754. if x==%1x goto noname
  755. basic b:%1
  756. goto end
  757. :noname
  758. echo BASIC programs in drive B: are
  759. dir b:*.bas/w/p
  760. :end
  761.  
  762. -----------------------------------------------------------------
  763.                          BASIC Unprotect
  764.                (PC World June 1986 Star-Dot-Star)
  765.  
  766.      BASIC files saved with the /P option can be unprotected with the
  767. 2-byte program UNPROT.BAS.  Because of its brevity, loading UNPROT.BAS
  768. resets the flag that indicates a program's protection status without
  769. overwriting the program already in memory.  UNPROT.BAS also works with
  770. programs that have been accidentally erased by the NEW command.
  771.      To use UNPROT.BAS, load the protected program first, then load
  772. UNPROT.BAS, and your program can be listed, edited and saved.
  773.  
  774. A>debug.com
  775. -e 100 ff 1a
  776. -n unprot.bas
  777. -r cx
  778. CX 0000
  779. :2
  780. -w
  781. Writing 0002 bytes
  782. -q
  783.  
  784.  
  785.